package com.ls.lsojcodesandbox.service;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ls.lsojcodesandbox.JavaDockerSandbox;
import com.ls.lsojcodesandbox.JudgeManager;
import com.ls.lsojcodesandbox.enums.JudgeInfoMessageEnum;
import com.ls.lsojcodesandbox.enums.QuestionSubmitStatusEnum;
import com.ls.lsojcodesandbox.mapper.QuestionMapper;
import com.ls.lsojcodesandbox.mapper.QuestionSubmitMapper;
import com.ls.lsojcodesandbox.model.ExecuteCodeRequest;
import com.ls.lsojcodesandbox.model.ExecuteCodeResponse;
import com.ls.lsojcodesandbox.model.JudgeInfo;
import com.ls.lsojcodesandbox.model.entity.JudgeCase;
import com.ls.lsojcodesandbox.model.entity.Question;
import com.ls.lsojcodesandbox.model.entity.QuestionSubmit;
import com.ls.lsojcodesandbox.strategy.JudgeContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CodeExecutionService {

    private static final Gson gson = new Gson();
    @Resource
    private JavaDockerSandbox javaDockerSandbox;

    @Resource
    private QuestionSubmitMapper questionSubmitMapper;

    @Resource
    private QuestionMapper questionMapper;

    @Resource
    private JudgeManager judgeManager;

    @Async() // 指定使用的线程池Bean的名称（推荐）
    public void execute(Long submitId) {
        log.info("开始异步执行代码任务...");
        try {
            //更新状态为判题中
            QuestionSubmit newQuestionSubmit = new QuestionSubmit();
            newQuestionSubmit.setId(submitId);
            newQuestionSubmit.setStatus(QuestionSubmitStatusEnum.RUNNING.getValue());
            questionSubmitMapper.updateById(newQuestionSubmit);
            //从数据库中获取题目的提交信息
            QuestionSubmit questionSubmit = questionSubmitMapper.selectById(submitId);
            ExecuteCodeRequest executeCodeRequest = new ExecuteCodeRequest();
            executeCodeRequest.setCode(questionSubmit.getCode());
            executeCodeRequest.setLanguage(questionSubmit.getLanguage());
            Question question = questionMapper.selectById(questionSubmit.getQuestionId());
            String judgeCaseStr = question.getJudgeCase();
            List<JudgeCase> judgeCaseList = JSONUtil.toList(judgeCaseStr, JudgeCase.class);

            List<String> inputList = judgeCaseList.stream().map(JudgeCase::getInput).collect(Collectors.toList());
            executeCodeRequest.setInputList(inputList);
            // 这里是真正耗时的操作
            ExecuteCodeResponse executeCodeResponse = javaDockerSandbox.executeCode(executeCodeRequest);
            JudgeContext judgeContext = new JudgeContext();
            log.error(executeCodeResponse.toString());
            judgeContext.setJudgeInfo(executeCodeResponse.getJudgeInfo());
            judgeContext.setJudgeCaseList(judgeCaseList);
            judgeContext.setQuestion(question);
            judgeContext.setInputList(inputList);
            judgeContext.setOutputList(executeCodeResponse.getOutputList());
            judgeContext.setQuestionSubmit(questionSubmit);
            judgeContext.setJudgeCaseList(judgeCaseList);
            JudgeInfo judgeInfo = judgeManager.doJudge(judgeContext);
            log.error(judgeInfo.toString());
            //更新状态为判题成功,同时将判题结果写到数据库中
            QuestionSubmit newAfterQuestionSubmit = new QuestionSubmit();
            if(judgeInfo.getMessage().equals(JudgeInfoMessageEnum.ACCEPTED.getValue())) {
                newAfterQuestionSubmit.setAccepted(JudgeInfoMessageEnum.ACCEPTED.getSign());
            }
            if(judgeInfo.getMessage().equals(JudgeInfoMessageEnum.WRONG_ANSWER.getValue())) {
                newAfterQuestionSubmit.setAccepted(JudgeInfoMessageEnum.WRONG_ANSWER.getSign());
            }
            newAfterQuestionSubmit.setId(submitId);
            newAfterQuestionSubmit.setJudgeInfo(gson.toJson(judgeInfo));
            newAfterQuestionSubmit.setStatus(executeCodeResponse.getStatus());
            questionSubmitMapper.updateById(newAfterQuestionSubmit);
            System.out.println(executeCodeResponse);
            log.info("代码任务执行完成。");
            // 可以在这里更新数据库状态、通知用户等
        } catch (Exception e) {
            log.error("异步执行代码任务失败", e);
            // 处理执行失败的逻辑，例如更新数据库状态为“失败”
        }
    }
}